package com.pwt.service;

import com.pwt.common.CustomException;
import com.pwt.common.ResultPage;
import com.pwt.model.*;
import com.pwt.model.crustallus.BoxModel;
import com.pwt.model.crustallus.FeatureModel;
import com.pwt.model.what.CharacteristicsModel;
import com.pwt.model.what.HeaderModel;
import com.pwt.model.what.OverviewModel;
import com.pwt.model.what.WhatDetailsModel;
import com.pwt.repository.WERTEVARRepository;
import com.pwt.utils.BoxUtils;
import com.pwt.utils.DoubleUtils;
import com.pwt.utils.MathUtil;
import com.pwt.utils.SigmaUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.*;

/**
 * @author dw
 * @version 1.0.0
 * @date 2021/9/23
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class WhatDetailsService {

    private WERTEVARRepository wertevarRepository;

    private SigmaUtil sigmaUtil;

    public WhatDetailsService(WERTEVARRepository wertevarRepository, SigmaUtil sigmaUtil) {
        this.wertevarRepository = wertevarRepository;
        this.sigmaUtil = sigmaUtil;
    }

    public WhatDetailsModel<CharacteristicsModel> getData(String k0014, Integer k0010, Integer page, Integer limit){
        HeaderModel headerModel= this.wertevarRepository.getHeader(k0014,k0010);
        if(headerModel == null) return null;
        String msg = this.wertevarRepository.hasError(k0014,k0010);
        if(StringUtils.isNotBlank(msg)){
            headerModel.setK0001(0);
            headerModel.setK0005(msg);
        }else {
            headerModel.setK0001(1);
        }
        ResultPage<CharacteristicsModel> resultPage = this.wertevarRepository.getList( k0014,  k0010, page, limit);
        WhatDetailsModel<CharacteristicsModel> whatDetailsModel = new WhatDetailsModel();
        whatDetailsModel.setHeaderModel(headerModel);
        whatDetailsModel.setResultPage(resultPage);
        return whatDetailsModel;
    }

    public ChartModel getListsAllValues(Integer k1000,Short k2000,Integer k0010,String k0014,Integer top) throws CustomException {
        ChartModel acceptanceLimit = sigmaUtil.getAcceptanceLimit(k1000, k2000);
        List<ChartValueModel> chartList = this.wertevarRepository.getListsAllValues(k1000,k2000,k0010,k0014,top);
        acceptanceLimit.setList(chartList);
        List list = new ArrayList();
        for (int i=0;i<chartList.size();i++) {
            List<Object> child = new ArrayList<>();
            if(chartList.get(i) != null){
                child.add(i);
                child.add(chartList.get(i).getK0001());
            }
            list.add(child);
        }
        acceptanceLimit.setCurveList(list);
        return acceptanceLimit;
    }


    public XbarRModel XBarAndRBar(Integer k1000,Short k2000,Integer k0010,String k0014) throws CustomException {
        XbarRModel xbarRModel = new XbarRModel();

        List<Double> xBarList = this.wertevarRepository.getWertOrderByK0014(k1000,k2000,k0010,k0014);
        List<Double> rBar = MathUtil.RXbar(xBarList);
        if(rBar == null) return null;
        xbarRModel.setXAvg(MathUtil.avg(xBarList)); //数据的均值Xbar
        xbarRModel.setXDown(MathUtil.subDouble(MathUtil.avg(xBarList),2.66*MathUtil.avg(rBar))); //下限 Xbar-2.66*Ｒbar
        xbarRModel.setXUp(MathUtil.addDouble(MathUtil.avg(xBarList),2.66*MathUtil.avg(rBar)));//上限  Xbar+2.66*Ｒbar
        xbarRModel.setXbarList(xBarList);

        xbarRModel.setRDown(0.00);//下限
        xbarRModel.setRUp(MathUtil.mulDouble(MathUtil.avg(rBar),3.267)); //上限 3.267*Ｒbar
        xbarRModel.setRAvg(MathUtil.avg(rBar));
        xbarRModel.setRbarList(rBar);
        return xbarRModel;
    }

    public WhatDetailsModel getOverViewValueChart(String k0014, Integer k0010, Integer page, Integer limit){
        HeaderModel headerModel= this.wertevarRepository.getHeader(k0014,k0010);
        ResultPage<OverviewModel> pageResult = this.wertevarRepository.getOverviewModel(k0014, k0010, page, limit);
        List<OverviewModel> list = (List<OverviewModel>) pageResult.getData();
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i) != null){
                if(list.get(i).getK2111() == null || list.get(i).getK2110() == null) continue;
                List<Double>  listValue = this.wertevarRepository.getMeasuredValue(list.get(i).getK1000(),list.get(i).getK2000(),k0010);
                Double avg = MathUtil.avg(listValue);
                list.get(i).setAvg(avg);
                list.get(i).setN(listValue.size());
                Double down = list.get(i).getK2110();
                Double up = list.get(i).getK2111();
                Double sigma = SigmaUtil.getSigma(listValue,avg);
                Double T = up - down;

                list.get(i).setSixSigma(MathUtil.mulDouble(6*1.00,sigma));
                //cp
                list.get(i).setCp(MathUtil.divDouble(T,6*sigma));
                Double cpu = MathUtil.divDouble((up - avg),3*sigma);
                cpu = DoubleUtils.retain2(cpu);
                Double cpl = MathUtil.divDouble((avg - down) , 3*sigma);
                cpl = DoubleUtils.retain2(cpl);
                //cpk
                list.get(i).setCpk(Math.min(cpu,cpl));
                if(list == null || list.size() < 1){
                    list.get(i).setStatus(3);
                }else{
                    if(list.get(i).getCp() >= list.get(i).getCpTarget()
                            && list.get(i).getCpk() >= list.get(i).getCpkTarget()){
                        if(list.size() <= 40 ){
                            list.get(i).setStatus(2);
                        }else{
                            list.get(i).setStatus(1);
                        }
                    }else{
                        list.get(i).setStatus(3);
                    }
                }
            }
        }

        WhatDetailsModel<OverviewModel> whatDetailsModel = new WhatDetailsModel();
        whatDetailsModel.setHeaderModel(headerModel);
        whatDetailsModel.setResultPage(pageResult);
        return whatDetailsModel;
    }


    public Map exportChart(Integer k1000,Short k2000,String beginTime,String endTime){
        Map<String,Object> map = new HashMap<>();

        CharacteristicsModel characteristics =this.wertevarRepository.queryCharacteristicsByK1000AndK2000(k1000,k2000);
        map.put("k1000",characteristics.getK1000());
        map.put("k1002",characteristics.getK1002());
        map.put("k2000",characteristics.getK2000());
        map.put("k2002",characteristics.getK2002());
        map.put("k2142",characteristics.getK2142());
        map.put("k2110",characteristics.getK2110());
        map.put("k2111",characteristics.getK2111());
        List<Double> list = this.wertevarRepository.queryWERTEVARByWVDATZEIT(k1000,k2000,beginTime,endTime);

        Integer nup = 0;
        Integer nDown = 0;

        Double down = characteristics.getK2110();//下限
        Double up = characteristics.getK2111();//上限
        for (Double val:list) {
            if(up != null && val > up){
                nup++;
            }else if(down != null && val < down){
                nDown++;
            }
        }
        Double Tm = MathUtil.divDouble((up+down),2*1.0);
        Double T = up-down;
        map.put("up",characteristics.getK2110());
        map.put("down",characteristics.getK2111());
        map.put("Tm",Tm);
        map.put("T",T);
        //测量值
        Double median = MathUtil.median(list);
        Double max = Collections.max(list);
        Double min = Collections.min(list);
        Integer n = list.size() - nup -nDown;//有效数量
        Integer nAll = (list == null || list.size() == 0) ? 0:list.size();
        String nt = n+"/"+((nAll == 0 ? 0 : n/nAll) * 100)+"%";
        String nupRate = nup+"/"+ ((nAll == 0 ? 0 :nup/nAll) * 100)+"%";
        String nDownRate = nup+"/"+((nAll == 0 ? 0 :nup/nAll) * 100)+"%";
        map.put("median",median);
        map.put("max",max);
        map.put("min",min);
        //极差R
        map.put("R",max-min);
        map.put("n",n);
        map.put("nAll",nAll);
        map.put("nt",nt);
        map.put("nupRate",nupRate);
        map.put("nDownRate",nDownRate);
        map.put("image","");
        //统计值
        Double avg = MathUtil.avg(list);
        //标准差
        Double s = MathUtil.StandardDiviation(list.toArray(new Double[0]));
        map.put("avg",avg);
        map.put("s",s);

        return map;
    }

}
